package com.chiangleoi.appointment.utils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.LinkedHashMap;

/**
 * http请求
 *
 * @author zhuming10
 */
public class HttpClientUtils {

    /**
     * 网络请求时发生异常
     */
    private static final String WEB_REQUEST_EXCEPTION = "网络请求时发生异常: {0}";

    /***
     * 向指定URL发送POST方法的请求
     *
     * @param apiUrl 请求路径
     * @param data  请求数据
     * @return
     * @throws Exception
     */
    public String sendPOST(String apiUrl, String data, LinkedHashMap<String, String> headers) throws Exception {
        // 获得响应内容
        String http_RespContent = null;
        int http_StatusCode = 0;
        String http_RespMessage = null;
        HttpURLConnection httpURLConnection = getHttpURLConnection(apiUrl, headers);
//        printHeaders(httpURLConnection);

        // 建立输入流，向指向的URL传入参数
        try (DataOutputStream dos = new DataOutputStream(httpURLConnection.getOutputStream())) {
            // 设置请求参数
            dos.write(data.getBytes(StandardCharsets.UTF_8.toString()));
            dos.flush();
            dos.close();
            // 获得响应状态(HTTP状态码)
            http_StatusCode = httpURLConnection.getResponseCode();
            // 获得响应消息(HTTP状态码描述)
            http_RespMessage = httpURLConnection.getResponseMessage();
            // 获得响应内容
            if (HttpURLConnection.HTTP_OK == http_StatusCode) {
                // 返回响应结果
                http_RespContent = getResponseContent(httpURLConnection);
            } else {
                // 返回非200状态时响应结果
                http_RespContent = getErrorResponseContent(httpURLConnection);
                String msg =
                        MessageFormat.format("请求失败: Http状态码 = {0} , {1}", http_StatusCode, http_RespMessage);
                System.out.println(msg);
            }
        } catch (UnknownHostException e) {
            String message = MessageFormat.format(WEB_REQUEST_EXCEPTION, e.getMessage());
            Exception ex = new Exception(message);
            ex.initCause(e);
            throw ex;
        } catch (MalformedURLException e) {
            String message = MessageFormat.format("格式错误的URL: {0}", e.getMessage());
            Exception ex = new Exception(message);
            ex.initCause(e);
            throw ex;
        } catch (IOException e) {
            String message = MessageFormat.format(WEB_REQUEST_EXCEPTION, e.getMessage());
            Exception ex = new Exception(message);
            ex.initCause(e);
            throw ex;
        } catch (Exception e) {
            String message = MessageFormat.format(WEB_REQUEST_EXCEPTION, e.getMessage());
            Exception ex = new Exception(message);
            ex.initCause(e);
            throw ex;
        } finally {
            if (null != httpURLConnection) {
                httpURLConnection.disconnect();
            }
        }
        return http_RespContent;
    }

    private void printHeaders(HttpURLConnection connection) {
        String[] headerNames = connection.getHeaderFields()
                .keySet()
                .toArray(new String[0]);

        // 打印所有响应头
        for (String headerName : headerNames) {
            System.out.println(headerName + ": " + connection.getHeaderField(headerName));
        }
    }

    /**
     * 获取连接
     *
     * @param apiUrl  请求地址
     * @param headers 请求头
     * @return 连接信息
     * @throws Exception 异常信息
     */
    public HttpURLConnection getHttpURLConnection(String apiUrl, LinkedHashMap<String, String> headers) throws Exception {
        // 建立连接
        URL url = new URL(apiUrl);
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();

        // 需要输出
        httpURLConnection.setDoOutput(true);
        // 需要输入
        httpURLConnection.setDoInput(true);
        // 不允许缓存
        httpURLConnection.setUseCaches(false);
        // HTTP请求方式
        httpURLConnection.setRequestMethod("POST");
        // 设置Headers
        if (null != headers) {
            for (String key : headers.keySet()) {
                httpURLConnection.setRequestProperty(key, headers.get(key));
            }
        }
        // 连接会话
        httpURLConnection.connect();
        return httpURLConnection;
    }

    /***
     * 读取HttpResponse响应内容
     *
     * @param httpURLConnection
     * @return
     * @throws UnsupportedEncodingException
     * @throws IOException
     */
    public String getResponseContent(HttpURLConnection httpURLConnection)
            throws UnsupportedEncodingException, IOException {
        StringBuffer contentBuffer = new StringBuffer();
        try (BufferedReader responseReader =
                     new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(), StandardCharsets.UTF_8.toString()))) {
            String readLine = null;
            while ((readLine = responseReader.readLine()) != null) {
                contentBuffer.append(readLine);
            }
        }
        return contentBuffer.toString();
    }

    /***
     * 读取HttpResponse响应内容
     *
     * @param httpURLConnection
     * @return
     * @throws UnsupportedEncodingException
     * @throws IOException
     */
    public String getErrorResponseContent(HttpURLConnection httpURLConnection)
            throws UnsupportedEncodingException, IOException {
        StringBuffer contentBuffer = null;
        try (BufferedReader responseReader =
                     new BufferedReader(new InputStreamReader(httpURLConnection.getErrorStream(), StandardCharsets.UTF_8.toString()))) {
            contentBuffer = new StringBuffer();
            String readLine = null;
            while ((readLine = responseReader.readLine()) != null) {
                contentBuffer.append(readLine);
            }
        }
        return contentBuffer.toString();
    }
}